package com.nxn.security.shiro.realm;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.nxn.core.model.Actions;
import com.nxn.core.model.Resources;
import com.nxn.core.model.Role;
import com.nxn.core.model.RoleAuth;
import com.nxn.core.model.User;
import com.nxn.core.service.RoleService;
import com.nxn.core.service.UserService;
import com.nxn.core.utils.CommonConstants;


@Service("monitorRealm")  
public class MonitorRealm extends AuthorizingRealm {  
      
	@Autowired 
	private UserService userService;
	
    @Autowired 
	private RoleService roleService;
      
    public MonitorRealm(){
        super();
    }
    
    /** 
     * 认证信息 
     */
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(  
            AuthenticationToken authcToken) throws AuthenticationException {  
		/* 这里编写认证代码 */

		// String hex = new Md5Hash("tt").toHex();

		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		String userName = token.getUsername();
		if (userName != null && !"".equals(userName)) {
			User user = userService.login(token.getUsername(), String.valueOf(token.getPassword()));

			if (user != null)
				return new SimpleAuthenticationInfo(user.getUsername(),
						user.getPassword(), getName());
		}
		return null;
	}
    
    
    /** 
     * 授权信息
     */ 
    @Override  
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		String username = (String) principals.fromRealm(getName()).iterator().next();
		if (StringUtils.isNotEmpty(username.trim())) {
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
			
			User user = userService.findUserByLoginName(username);
			if (user != null && user.getRoles() != null) {

				Set<Role> roles = user.getRoles();
				for (Iterator<Role> iterator = roles.iterator(); iterator.hasNext();) {
					Role role = iterator.next();
					info.addRole(role.getName());
					
					info.addStringPermissions(getPermissionsAsString(role));
				}
			}
			return info;
		}
		
		return null;
	}

    public void clearCachedAuthorizationInfo(String principal) {  
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());  
        clearCachedAuthorizationInfo(principals);  
    }

    private Collection<String> getPermissionsAsString(Role role) {
    	Collection<String> permissions = new ArrayList<String>();
    	
    	Map<String, List<String>> resourceMap = getResourceMap(role);
    	
    	for(Entry<String, List<String>> entry : resourceMap.entrySet()){
    		String resourceName = entry.getKey();
    		List<String> actions = entry.getValue();
    		
    		StringBuilder builder = new StringBuilder();
    		permissions.add(builder.append(resourceName).append(CommonConstants.COLON)
        			.append(StringUtils.join(actions, CommonConstants.COMMA)).toString());
    	}
    	
    	return permissions;
    }
    
    
    private Map<String, List<String>> getResourceMap(Role role) {
    	Map<String, List<String>> resourceMap = new HashMap<String, List<String>>();
    	Set<RoleAuth> auths = role.getRoleAuths();
		for (Iterator<RoleAuth> iter = auths.iterator(); iter.hasNext();) {
			RoleAuth roleAuth = iter.next();

			Resources resource = roleAuth.getResource();
			Actions action = roleAuth.getAction();

			List<String> actions = resourceMap.get(resource.getName());
			if(actions == null) {
				actions = new ArrayList<String>();
				resourceMap.put(resource.getName(), actions);
			}
			actions.add(action.getName());
			
			System.out.println(resource.getName() + " : " + action.getName());
		}
    	return resourceMap;
    }
    
}  
